﻿using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using ManaMaple.Auth.Models;
using ManaMaple.Kit.Models;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Http;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace ManaMaple.Auth.Helpers
{
    /// <summary>
    /// 描述：Jwt服务类
    /// </summary>
    public class JwtHelper
    {
        /// <summary>
        /// 创建Token
        /// </summary>
        /// <param name="tokenManagement"></param>
        /// <param name="uesr"></param>
        /// <returns></returns>
        public static JwtModel CreateToken(JwtConfig tokenManagement, CurrentUserModel uesr)
        {
            string userInfo = JsonConvert.SerializeObject(uesr);
            var authClaims = new[]
            {
                new Claim("User", userInfo),
                new Claim(JwtRegisteredClaimNames.Sub, uesr.UserID.ToString()),
                new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
            };
            //IdentityModelEventSource.ShowPII = true;
            // 取出私钥并以utf8编码字节输出
            // 使用非对称算法对私钥进行加密
            var authSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(tokenManagement.SecretKey));
            /**
             * Claims(payload)
             * Claims 部分包含了一些跟这个 token 有关的重要信息，JWT标准规定了一些字段，下面节选一些字段
             * 
             * iss: the issuer of the token,token 是给谁的
             * sub: the subject of the token,token 主题
             * exp : token 过期时间 unix 时间戳格式
             * iat: token 创建时间，unix 时间戳格式
             * jti: JWT ID 针对当前token的唯一标识
             *  除了规定的字段外，可以包含其他任何JSON兼容的字段
             * */
            var token = new JwtSecurityToken(
              issuer: tokenManagement.Issuer,
              audience: tokenManagement.Audience,
              claims: authClaims,
              // 使用HmacSha256来验证加密后的私钥生成数字签名
              signingCredentials: tokenManagement.SigningCredentials,
              notBefore: DateTime.Now,
              expires: DateTime.Now.AddHours(tokenManagement.AccessExpiration)
              );
            string returnToken = new JwtSecurityTokenHandler().WriteToken(token);
            //return new
            //{
            //    Token = returnToken,
            //    expiration = token.ValidTo
            //};
            return new JwtModel() { Token = returnToken, Expiration = token.ValidTo };
        }

        /// <summary>
        /// 获取Jwt的信息
        /// </summary>
        /// <param name="authorization"></param>
        /// <returns></returns>
        public static JwtPayload Decode(string authorizationToken)
        {
            // var authorization = request.Headers["Authorization"].ToString();
            //因为我们的Jwt是自带【Bearer 】这个请求头的，所以去掉前面的头
            var auth = authorizationToken.Split(" ")[1];
            var handler = new JwtSecurityTokenHandler();
            //反解密，获取其中的Claims
            var payload = handler.ReadJwtToken(auth).Payload;
            return payload;
        }

        /// <summary>
        /// 解析得到User
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public static CurrentUserModel DecodeToUser(string authorizationToken)
        {
            CurrentUserModel currentUserModel = null;
            // HttpRequest request 
            var payload = Decode(authorizationToken);
            var claims = payload.Claims;
            if (claims != null && claims.Count() > 0)
            {
                currentUserModel = JsonConvert.DeserializeObject<CurrentUserModel>(claims?.Where(t => t.Type == "User")?.First().Value);
            }
            return currentUserModel;
        }
    }
}
